﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using Microsoft.WVB.Framework;
using Microsoft.WVB.Framework.Entities;

namespace Microsoft.WVB.Services
{
    public class EPGEntityVisitor : EntityVisitor
    {
        protected override void VisitProperties(Microsoft.WVB.Framework.Entities.BaseEntity entity)
        {
            base.VisitProperties(entity);

            XNamespace m = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";

            StringBuilder sb = new StringBuilder();
            using (XmlWriter xw = XmlWriter.Create(sb))
            {
                item.Content.WriteTo(xw, "Content", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");
            }

            XDocument xdoc = XDocument.Parse(sb.ToString(), LoadOptions.None);
            XElement prop = xdoc.Descendants(m + "properties").First();

            if (entity.GetType() == typeof(Broadcaster))
            {

                Broadcaster bc = entity as Broadcaster;

                try
                {
                    Uri result = null;
                    setPropertyValue<Broadcaster, String>(bc, "ID", getElementValue("id", prop));
                    setPropertyValue<Broadcaster, String>(bc, "Name", getElementValue("Name", prop));
                    
                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Broadcaster, Uri>(bc, "Icon", result);
                    }

                    if (Uri.TryCreate(getElementValue("WebSite", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Broadcaster, Uri>(bc, "WebSite", result);
                    }

                    setPropertyValue<Broadcaster, String>(bc, "Description", getElementValue("Description", prop));
                    setPropertyValue<Broadcaster, String>(bc, "Country", getElementValue("Country", prop));
                }
                catch (Exception ex) 
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }

                entity = bc;
            }
            else if (entity.GetType() == typeof(Channel))
            {
                Channel c = entity as Channel;
                try
                {
                    Uri result = null;
                    setPropertyValue<Channel, String>(c, "Name", getElementValue("Name", prop));
                    
                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Channel, Uri>(c, "Icon", result);
                    }
                    setPropertyValue<Channel, String>(c, "ID", getElementValue("cid", prop));
                    setPropertyValue<Channel, String>(c, "LongName", getElementValue("LongName", prop));
                    setPropertyValue<Channel, String>(c, "Description", getElementValue("Description", prop));
                    setPropertyValue<Channel, String>(c, "ProgramType", getElementValue("ProgramType", prop));
                    setPropertyValue<Channel, String>(c, "Language", getElementValue("Language", prop));
                    
                    if (Uri.TryCreate(getElementValue("Url", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Channel, Uri>(c, "Url", result);
                    }
                    
                    setPropertyValue<Channel, String>(c, "TimeZone", getElementValue("TimeZone", prop));

                    entity = c;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(Program))
            {
                Program p = entity as Program;
                try
                {
                    Uri result = null;
                    setPropertyValue<Program, String>(p, "Name", getElementValue("Name", prop));

                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Program, Uri>(p, "Icon", result);
                    }

                    setPropertyValue<Program, String>(p, "ID", getElementValue("programid", prop));
                    setPropertyValue<Program, String>(p, "EpisodeTitle", getElementValue("EpisodeTitle", prop));
                    setPropertyValue<Program, String>(p, "ShortTite", getElementValue("LongName", prop));
                    setPropertyValue<Program, String>(p, "Description", getElementValue("Description", prop));
                    setPropertyValue<Program, String>(p, "ShortDescription", getElementValue("ProgramType", prop));
                    setPropertyValue<Program, String>(p, "Language", getElementValue("Language", prop));
                    
                    if (Uri.TryCreate(getElementValue("LowResolutionLink", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Program, Uri>(p, "LowResolutionLink", result);
                    }

                    if (Uri.TryCreate(getElementValue("HighResolutionLink", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<Program, Uri>(p, "HighResolutionLink", result);
                    }


                    entity = p;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(ProgramFlag))
            {
                ProgramFlag pf = entity as ProgramFlag;
                try
                {
                    Uri result = null;
                    setPropertyValue<ProgramFlag, String>(pf, "Name", getElementValue("Name", prop));
                    
                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<ProgramFlag, Uri>(pf, "Icon", result);
                    }

                    setPropertyValue<ProgramFlag, String>(pf, "ID", getElementValue("pfid", prop));
                    setPropertyValue<ProgramFlag, String>(pf, "pname", getElementValue("pname", prop));
                    setPropertyValue<ProgramFlag, String>(pf, "Description", getElementValue("Description", prop));
                    setPropertyValue<ProgramFlag, String>(pf, "Language", getElementValue("Language", prop));

                    entity = pf;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(ProgramProperty))
            {
                ProgramProperty pp = entity as ProgramProperty;
                try
                {
                    Uri result = null;

                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<ProgramProperty, Uri>(pp, "Icon", result);
                    }

                    setPropertyValue<ProgramProperty, String>(pp, "ID", getElementValue("pvid", prop));
                    setPropertyValue<ProgramProperty, String>(pp, "Value", getElementValue("Value", prop));
                    
                    entity = pp;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(ProgramPropertyInfo))
            {
                ProgramPropertyInfo pp = entity as ProgramPropertyInfo;
                try
                {
                    Uri result = null;

                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<ProgramPropertyInfo, Uri>(pp, "Icon", result);
                    }

                    setPropertyValue<ProgramPropertyInfo, String>(pp, "ID", getElementValue("pvid", prop));
                    setPropertyValue<ProgramPropertyInfo, String>(pp, "Name", getElementValue("Name", prop));
                    setPropertyValue<ProgramPropertyInfo, String>(pp, "pname", getElementValue("pname", prop));
                    setPropertyValue<ProgramPropertyInfo, String>(pp, "Description", getElementValue("Description", prop));
                    setPropertyValue<ProgramPropertyInfo, String>(pp, "Language", getElementValue("Language", prop));

                    entity = pp;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(Schedule))
            {
                Schedule s = entity as Schedule;
                try
                {
                    setPropertyValue<Schedule, String>(s, "ID", getElementValue("pvid", prop));
                    setPropertyValue<Schedule, String>(s, "Start", getElementValue("start", prop));
                    setPropertyValue<Schedule, String>(s, "Duration", getElementValue("Duration", prop));

                    entity = s;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(ScheduleFlag))
            {
                ScheduleFlag sf = entity as ScheduleFlag;
                try
                {
                    setPropertyValue<ScheduleFlag, String>(sf, "ID", getElementValue("pvid", prop));
                    setPropertyValue<ScheduleFlag, String>(sf, "Name", getElementValue("Name", prop));
                    setPropertyValue<ScheduleFlag, String>(sf, "pname", getElementValue("pname", prop));
                    setPropertyValue<ScheduleFlag, String>(sf, "Description", getElementValue("Description", prop));
                    setPropertyValue<ScheduleFlag, String>(sf, "Language", getElementValue("Language", prop));

                    entity = sf;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(SchedulePropertyInfo))
            {
                SchedulePropertyInfo spi = entity as SchedulePropertyInfo;
                try
                {
                    Uri result = null;

                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<SchedulePropertyInfo, Uri>(spi, "Icon", result);
                    }
                    setPropertyValue<SchedulePropertyInfo, String>(spi, "ID", getElementValue("svid", prop));
                    setPropertyValue<SchedulePropertyInfo, String>(spi, "Name", getElementValue("Name", prop));
                    setPropertyValue<SchedulePropertyInfo, String>(spi, "pname", getElementValue("pname", prop));
                    setPropertyValue<SchedulePropertyInfo, String>(spi, "Description", getElementValue("Description", prop));
                    setPropertyValue<SchedulePropertyInfo, String>(spi, "Language", getElementValue("Language", prop));
                    
                    entity = spi;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(ScheduleProperty))
            {
                ScheduleProperty sp = entity as ScheduleProperty;
                try
                {
                    Uri result = null;

                    if (Uri.TryCreate(getElementValue("Icon", prop), UriKind.RelativeOrAbsolute, out result))
                    {
                        setPropertyValue<ScheduleProperty, Uri>(sp, "Icon", result);
                    }
                    setPropertyValue<ScheduleProperty, String>(sp, "ID", getElementValue("pvid", prop));
                    setPropertyValue<ScheduleProperty, String>(sp, "Value", getElementValue("val", prop));

                    entity = sp;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(Category))
            {
                Category sp = entity as Category;
                try
                {
                    setPropertyValue<Category, String>(sp, "ID", getElementValue("pcid", prop));
                    setPropertyValue<Category, String>(sp, "Value", getElementValue("Value", prop));
                    setPropertyValue<Category, String>(sp, "Name", getElementValue("Name", prop));

                    entity = sp;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }

            if (entity.GetType() == typeof(People))
            {
                People p = entity as People;
                try
                {
                    setPropertyValue<People, String>(p, "ID", getElementValue("orderid", prop));

                    entity = p;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(PeopleInformation))
            {
                PeopleInformation pi = entity as PeopleInformation;
                try
                {
                    setPropertyValue<PeopleInformation, String>(pi, "ID", getElementValue("nameid", prop));
                    setPropertyValue<PeopleInformation, String>(pi, "FirstName", getElementValue("FirstName", prop));
                    setPropertyValue<PeopleInformation, String>(pi, "MiddleName", getElementValue("MiddleName", prop));
                    setPropertyValue<PeopleInformation, String>(pi, "LastName", getElementValue("LastName", prop));

                    entity = pi;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else if (entity.GetType() == typeof(PeopleRole))
            {
                PeopleRole pi = entity as PeopleRole;
                try
                {
                    setPropertyValue<PeopleRole, String>(pi, "ID", getElementValue("roleid", prop));
                    setPropertyValue<PeopleRole, String>(pi, "Name", getElementValue("Name", prop));
                    setPropertyValue<PeopleRole, String>(pi, "Description", getElementValue("Description", prop));

                    entity = pi;
                }
                catch (Exception ex)
                {
                    throw new WVBException("An error occured during entity Deserialization", ex);
                }
            }
            else
                entity = null;
        }


        private static void setPropertyValue<T,K>(T entity, string propertyName, K value) where T: class
        {
            Type entityType = typeof(T);
            Type propertyType = typeof(K);

            PropertyInfo pi = entityType.GetProperty(propertyName);
            if ((pi != null) && (pi.PropertyType == propertyType))
            {
                pi.SetValue(entity, value, null);
            }
        }

        private static string getElementValue(string name, XElement element)
        {
            XNamespace d = "http://schemas.microsoft.com/ado/2007/08/dataservices";

            if ((element.Element(d + name) != null) && (element.Element(d + name).Value != String.Empty))
                return element.Element(d + name).Value;
            else
                return String.Empty;
        }
    }
}
